/* 
 * File:   ServerPid.cpp
 * Author: dell
 * 
 * Created on 2012年4月5日, 下午1:23
 */

#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <signal.h>
#include "ServerPid.h"

using namespace std;

namespace Rapid{
    ServerPid::ServerPid(const char* homeDir, int port){
//        serverPidDir.append("conf/");
        char portbuf[32];
        sprintf(portbuf, "%d", port);
//        this->port.append(portbuf);
        serverPidFilename.append(homeDir).append("conf/").append("server_").append(portbuf).append(".pid");
    }

    ServerPid::ServerPid(const char* serverPidFilename):serverPidFilename(serverPidFilename){
        LOG_DEBUG("serverPidFilename:%s", serverPidFilename);
    }
    
    ServerPid::~ServerPid() {
    }

    /** 返回从server.pid文件中读出的pid */
    pid_t ServerPid::read(){
        FD spidfd = ::open(serverPidFilename.c_str(), O_RDONLY | O_SYNC);
        if(spidfd < 0){
            LOG_ERROR("open %s file error, errno:%d", serverPidFilename.c_str(), errno);
            return -1;
        }
        char pidbuf[32];
        ssize_t rsize = ::read(spidfd, pidbuf, 32);
        if(rsize <= 0){
            LOG_ERROR("read %s file error, errno:%d", serverPidFilename.c_str(), errno);
            return -1;
        }
        pidbuf[rsize] = 0;
        return atol(pidbuf);
    }

    /** 将pid追加到server.pid文件 */
    bool ServerPid::append(pid_t pid){
        char pidbuf[32];
        sprintf(pidbuf, "%ld", pid);        

//        string serverPidFilename = serverPidDir;
//        serverPidFilename.append("server_").append(port).append(".pid");
        FD spidfd = ::open(serverPidFilename.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_SYNC, S_IRWXU | S_IRWXG | S_IRWXO);
        if(spidfd < 0){
            LOG_ERROR("create %s file error, errno:%d", serverPidFilename.c_str(), errno);
            return false;
        }
        
        char* pidbufPt = &pidbuf[0];
        int len = strlen(pidbuf);
        ssize_t wsize = -1;
        do{
            wsize = ::write(spidfd, pidbufPt, len);
            if(wsize == len){
                break;
            }
            if(wsize < 0){
                if(ERRNO_IS_AGAIN()){
                    continue;
                }
                LOG_ERROR("write %s file error, errno:%d", serverPidFilename.c_str(), errno);
                break;
            }else{
                len -= wsize;
                pidbufPt += wsize;
            }
        }while(1);
        ::close(spidfd);
        return wsize > 0;
    }

    bool ServerPid::remove(){
        LOG_DEBUG("%s", serverPidFilename.c_str());
        if(::remove(serverPidFilename.c_str()) < 0){
            LOG_ERROR("remove %s file error, errno:%d", serverPidFilename.c_str(), errno);
            return false;
        }
        return true;
    }

    bool ServerPid::existFile(){
        //LOG_DEBUG("access(%s, F_OK):%d", serverPidFilename.c_str(), access(serverPidFilename.c_str(), F_OK))
        return access(serverPidFilename.c_str(), F_OK) == 0;
    }

    
    bool ServerPid::existProcess(){
        LOG_DEBUG("existFile():%d", existFile())
        if(existFile()){
            pid_t pid = read();
            LOG_DEBUG("pid:%d", pid);
            if(pid > -1){
                int flag = kill(pid, 0);
                LOG_DEBUG("flag:%d, ESRCH:%d, errno:%d", flag, ESRCH, errno);
                return !(flag == -1 && errno == ESRCH);
            }
            
        }
        return false;
    }
    
}

